<template>
  <div class="sz-tag-input">
    <template v-if="signList.length">
      <div v-for="(item, index) in signList" :key="index">
        <div
          class="signed-box"
          :class="[item.type, outConfig.signInline ? 'sign-inline' : '']"
        >
          <template
            v-if="item.type === 'text_sign' || item.type === 'click_sign'"
          >
            <p class="text">
              {{ item.text }}
            </p>
          </template>
          <template
            v-if="
              item.type === 'hand_sign' ||
                item.type === 'template' ||
                item.type === 'photo'
            "
          >
            <div class="signed-text-box">
              <div class="img-box">
                <rate-img
                  :src-url="item.img || item.sign"
                  :index="item.index"
                  :v-z="0"
                  :is-draggable="false"
                  :v-height="item.height"
                  :v-width="item.width"
                  :is-active="false"
                  :parentLimitation="false"
                  v-if="showEditBox(item)"
                  @getRect="getRect($event, item, index)"
                  class="cut_sign_area"
                  style="max-width: 100%"
                ></rate-img>
                <el-image
                  style="max-width: 100%"
                  :style="{
                    width: item.width ? `${item.width}px` : '200px',
                    height: item.height ? `${item.height}px` : '60px'
                  }"
                  :src="item.img || item.sign"
                  :preview-src-list="[item.img || item.sign]"
                  v-else
                >
                </el-image>
              </div>
            </div>
          </template>
          <template v-if="item.type === 'text_and_sign'">
            <p class="text">
              {{ item.text }}
            </p>
            <div class="img-box">
              <rate-img
                :src-url="item.img || item.sign"
                :index="item.index"
                :v-z="0"
                :is-draggable="false"
                :v-height="item.height"
                :v-width="item.width"
                :is-active="false"
                :parentLimitation="false"
                v-if="showEditBox(item)"
                @getRect="getRect($event, item, index)"
                class="cut_sign_area"
                style="max-width: 100%"
              ></rate-img>
              <el-image
                style="max-width: 100%"
                :style="{
                  width: item.width ? `${item.width}px` : '200px',
                  height: item.height ? `${item.height}px` : '60px'
                }"
                :src="item.img || item.sign"
                :preview-src-list="[item.img || item.sign]"
                v-else
              >
              </el-image>
            </div>
          </template>
          <p class="sign-date">
            <span
              v-if="
                showSign &&
                  (item.type === 'text_sign' || item.type === 'click_sign')
              "
              >{{ item.sign }}
            </span>
            <span v-if="showDate">{{ item.date }}</span>
          </p>
          <div class="edit-box" v-if="showEditBox(item)">
            <el-button size="mini" type="text" @click="editSign(item, index)">
              编 辑
            </el-button>
            <el-button
              size="mini"
              class="del"
              type="text"
              @click="removeSign(item, index)"
            >
              删 除
            </el-button>
          </div>
        </div>
      </div>
    </template>
    <template v-if="signType === 'text_sign' && !this.readonly">
      <textSign v-model="onlyTextSign" />
    </template>
    <template v-if="showControl">
      <div class="sign-box" @click="signClick">
        <i class="el-icon-edit-outline m_r_10"></i>点击签名
      </div>
    </template>

    <signModal v-model="showSignModal" @selectSign="selectSign" />
    <textSignModal
      v-model="showTextModal"
      :modalData="checkData"
      :isUpdata="isUpdata"
      @confirm="modalConfirm($event, { show: 'showTextModal' })"
    />
    <textTemplateSign
      v-model="showTextTemplateModal"
      @addTemplate="addTemplate"
      :modalData="checkData"
      :autoTemplateList="autoTemplateList"
      :isUpdata="isUpdata"
      @confirm="modalConfirm($event, { show: 'showTextTemplateModal' })"
    />
    <templateSign
      v-model="showTemplateModal"
      :modalData="checkData"
      :isUpdata="isUpdata"
      @confirm="modalConfirm($event, { show: 'showTemplateModal' })"
    />
  </div>
</template>

<script>
import _ from "lodash";
import textSign from "./components/tag-input/textSign";
import textSignModal from "./components/tag-input/textSignModal";
import textTemplateSign from "./components/tag-input/textTemplateSign";
import templateSign from "./components/tag-input/templateSign";
import signModal from "./components/tag-input/signModal";
import uuidMixin from "@/mixins/uuid";
import { mapActions } from "vuex";

export default {
  name: "WorkspaceJsonSzTagInput",

  mixins: [uuidMixin],

  components: {
    textSign,
    signModal,
    textTemplateSign,
    templateSign,
    textSignModal
  },

  props: {
    config: {
      type: [Object],
      default: () => {
        return {};
      }
    },
    readonly: {
      type: [Boolean],
      default: false
    },
    placeholder: {
      type: [String],
      default: ""
    },
    disabled: {
      type: [Boolean],
      default: false
    },
    value: {
      type: [Array],
      default: () => {
        return [];
      }
    }
  },

  provide() {
    return {
      designerConfig: () => {
        return {
          ...this.outConfig,
          readonly: this.readonly,
          placeholder: this.placeholder,
          disabled: this.disabled
        };
      }
    };
  },

  data() {
    return {
      // 表单数据
      onlyTextSign: {},
      textSign: {},
      imgSign: {},
      // 弹框类型
      signTypeChecked: {},
      // 弹框显隐
      showSignModal: false,
      showTextModal: false,
      showTextTemplateModal: false,
      showTemplateModal: false,
      // 默认配置
      defaultConfig: {},
      userInfo:
        window.sessionStorage.getItem("userInfo") &&
        JSON.parse(window.sessionStorage.getItem("userInfo")).user,
      // socket loading
      loading: null,
      // 签名列表
      signList: [],
      // 编辑
      editIndex: -1,
      checkData: {},
      // 文本+签名 自定义签名
      autoTemplateList: []
    };
  },

  computed: {
    // 输出config
    outConfig() {
      return { ...this.defaultConfig, ...this.config };
    },
    // 是否显示签名
    showSign() {
      if (this.config.showSign === false) {
        return false;
      }
      return true;
    },
    // 是否显示日期
    showDate() {
      if (this.config.showDate === false) {
        return false;
      }
      return true;
    },
    // 只有一种签名时的类型
    signType() {
      if (this.config.tagType && this.config.tagType.length === 1) {
        return this.config.tagType[0];
      }
      return "all_sign";
    },
    // 当前的签名列表
    currentSignList() {
      return this.signList.filter(item => {
        return item.nowStep;
      });
    },
    // 签名内是否包含当前用户
    isHaveCurrentUser() {
      if (!this.signList.length) {
        return false;
      }
      return this.signList.some(item => {
        return item.userId === this.userInfo.userId;
      });
    },
    // 是否显示点击签名控件
    showControl() {
      if (!this.outConfig.allowRepeat && this.isHaveCurrentUser) {
        return false;
      }
      if (this.signType === "text_sign") {
        return false;
      }
      if (this.readonly) {
        return false;
      }
      if (!this.config.tagType || !this.config.tagType.length) {
        return false;
      }
      if (this.currentSignList.length && !this.config.continuitySign) {
        return false;
      }
      return true;
    },
    // 是否是编辑
    isUpdata() {
      return this.editIndex >= 0;
    },
    // 是否有图片
    isImgSign() {
      if (
        this.signTypeChecked.key === "template" ||
        this.signTypeChecked.key === "photo" ||
        this.signTypeChecked.key === "hand_sign" ||
        this.signTypeChecked.key === "text_and_sign"
      ) {
        return true;
      }
      return false;
    }
  },

  watch: {
    onlyTextSign: {
      handler: function(n) {
        if (this.signType === "text_sign") {
          const { userId, name } = this.userInfo;
          if (n.sign || n.text) {
            let obj = {
              ...n,
              userId,
              userName: name,
              type: "text_sign"
            };
            if (!obj.text) {
              obj.text = "";
            }
            this.$emit("input", [...this.signList, obj]);
            this.$store.dispatch("mergeFormDataAction", {
              [this.config.__vModel__]: [...this.outConfig.defaultValue, obj]
            });
          } else {
            this.$emit("input", this.signList || []);
            this.$store.dispatch("mergeFormDataAction", {
              [this.config.__vModel__]: this.outConfig.defaultValue || []
            });
          }
        }
      },
      deep: true,
      immediate: true
    },
    // 因为有render函数存在  会一直触发
    readonly: {
      handler: function(n, o) {
        if (n != o) {
          // 初始化数据
          this.initSignList();
        }
      },
      deep: true,
      immediate: true
    }
  },

  mounted() {
    this.initSignList();
  },

  methods: {
    ...mapActions({
      sendSocket: "sendSocket"
    }),
    // 初始化signList
    initSignList() {
      if (!this.config.defaultValue) {
        return;
      }
      if (this.config.defaultValue.length) {
        // 初始化数据
        // 初始化数据reduceImg
        const arr = [];
        this.config.defaultValue.forEach(item => {
          const sizeObj = this.reduceImg(item.width, item.height);
          arr.push({ ...item, ...sizeObj });
        });
        this.signList = arr;
      } else {
        this.signList = [];
      }
      this.emitData();
    },
    // 抛出表单值
    emitData() {
      let arr = this.signList.map(item => {
        let obj = _.cloneDeep(item);
        delete obj.nowStep;
        return obj;
      });
      this.$emit("input", arr);
      if (this.config.isMerge) {
        this.$store.dispatch("mergeFormDataAction", {
          [this.config.__vModel__]: arr
        });
      }
    },
    // 获取base64图片的宽高
    getBase64WidthAndHeight(item) {
      const _this = this;
      const { sign, img } = item;
      let signImg = img || sign;
      var imgEle = new Image();
      imgEle.src = signImg;
      return new Promise((resolve, reject) => {
        imgEle.onload = () => {
          resolve(this.reduceImg(imgEle.width, imgEle.height));
        };
        imgEle.onerror = () => {
          reject();
        };
      });
    },
    // 处理图片宽高
    reduceImg(width = 450, height = 450) {
      const min = parseInt(this.outConfig.signMinSize || 200);
      const max = parseInt(this.outConfig.signMaxSize || 300);
      const isMin = width < min && height < min;
      const isMax = width > max && height > max;
      if (!isMin && !isMax) {
        return { width, height };
      }
      if (width > height) {
        let scaleBeta = width / max;
        if (isMin) {
          scaleBeta = width / min;
        }
        return { width: isMin ? min : max, height: height / scaleBeta };
      } else {
        let scaleBeta = height / max;
        if (isMin) {
          scaleBeta = height / min;
        }
        return { width: width / scaleBeta, height: isMin ? min : max };
      }
    },
    // 拖动该更图片大小
    getRect(rect, item, index) {
      const { width, height } = rect;
      this.$set(item, "width", width);
      this.$set(item, "height", height);
      this.emitData();
    },
    // 是否显示编辑和删除
    showEditBox(item) {
      if (this.readonly && !item.nowStep) {
        return false;
      }
      if (!this.config.editOldSign && !item.nowStep) {
        return false;
      }
      if (item.userId !== this.userInfo.userId) {
        return false;
      }
      return true;
    },
    // 添加签名列表
    async addSignList() {
      const { text, date, sign } = this.textSign;
      const { text: imgText, img, width, height } = this.imgSign;
      const { key } = this.signTypeChecked;
      const { userId, name } = this.userInfo;
      let obj = {
        date,
        sign,
        userId,
        userName: name,
        type: key === "click_sign" ? "text_sign" : key
      };
      if (this.isImgSign) {
        // 模板签名需要这个时间，不然导出签没有图片
        obj.date = new Date().Format(this.config.format);
        obj.sign = img || "";
        // obj.img = img;
        obj.width = width;
        obj.height = height;
        if (key === "text_and_sign") {
          obj.text = imgText || "";
        }
      } else {
        obj.text = text || "";
      }
      if (!obj.text) {
        obj.text = "";
      }
      if (!obj.align) {
        obj.align = "left";
      }
      // 如果有编辑序号就是编辑
      if (this.editIndex >= 0) {
        this.signList.splice(this.editIndex, 1, {
          ...obj,
          nowStep: true
        });
        this.emitData();
        return;
      }
      this.signList.push({
        ...obj,
        nowStep: true
      });
      this.emitData();
    },
    // 删除签名列表
    removeSign(item, index) {
      this.signList.splice(index, 1);
      this.emitData();
    },
    // socket回调
    socketCallback(val) {
      let _this = this;
      const { key: type } = this.signTypeChecked;
      const { sign } = val;
      let obj = {
        hand_sign: async function() {
          _this.$set(_this.imgSign, "img", sign);
          try {
            const imgInfo = await _this.getBase64WidthAndHeight(val);
            _this.imgSign.width = imgInfo.width;
            _this.imgSign.height = imgInfo.height;
          } catch {
            console.log("加载图片失败");
          }
          _this.autoSetDefault();
          _this.addSignList();
        },
        photo: async function() {
          _this.$set(_this.imgSign, "img", sign);
          try {
            const imgInfo = await _this.getBase64WidthAndHeight(val);
            _this.imgSign.width = imgInfo.width;
            _this.imgSign.height = imgInfo.height;
          } catch {
            console.log("加载图片失败");
          }
          _this.autoSetDefault();
          _this.addSignList();
        },
        text_and_sign: function() {
          _this.autoTemplateList.push(sign);
        }
      };
      try {
        obj[type] && obj[type]();
      } finally {
        this.showSignModal = false;
        this.closeLoading();
      }
    },
    // socket错误回调
    socketCallbackErr(val) {
      this.closeLoading();
    },
    // 关闭socket loading
    closeLoading() {
      if (this.loading) {
        this.loading.close();
      }
    },
    // 编辑签名
    editSign(item, index) {
      this.checkData = _.cloneDeep(item);
      const _this = this;
      const { type } = item;
      let obj = {
        text_sign: function() {
          _this.showTextModal = true;
        },
        click_sign: function() {
          _this.showTextModal = true;
        },
        hand_sign: function() {
          _this.upSign(item);
        },
        photo: function() {
          _this.upSign(item);
        },
        template: function() {
          _this.showTemplateModal = true;
        },
        text_and_sign: function() {
          _this.showTextTemplateModal = true;
        }
      };
      if (obj[type]) {
        this.signTypeChecked.key = type;
        this.editIndex = index;
        obj[type]();
      }
    },
    // 弹窗取消
    modalCancle(val) {
      const { show } = val;
      this.$set(this.$data, show, false);
    },
    // 弹窗确认
    async modalConfirm(val, modalConfig) {
      const { show } = modalConfig;
      if (show === "showTextModal") {
        this.textSign = _.cloneDeep(val);
      }
      if (show === "showTextTemplateModal") {
        this.imgSign = _.cloneDeep(val);
        try {
          const imgInfo = await this.getBase64WidthAndHeight(val);
          this.imgSign.width = imgInfo.width;
          this.imgSign.height = imgInfo.height;
        } catch {
          console.log("加载图片失败");
        }
      }
      if (show === "showTemplateModal") {
        this.imgSign = _.cloneDeep(val);
        try {
          const imgInfo = await this.getBase64WidthAndHeight(val);
          this.imgSign.width = imgInfo.width;
          this.imgSign.height = imgInfo.height;
        } catch {
          console.log("加载图片失败");
        }
      }
      this.$set(this.$data, "showSignModal", false);
      this.$set(this.$data, show, false);
      this.autoSetDefault();
      this.addSignList();
    },
    // 选中某一个签名类型
    selectSign(val) {
      this.editIndex = -1;
      let _this = this;
      const { key } = val;
      let obj = {
        text_sign: function() {
          _this.showTextModal = true;
        },
        click_sign: function() {
          _this.clickSign();
          _this.$set(_this.$data, "showSignModal", false);
          _this.addSignList();
          return;
        },
        hand_sign: function() {
          _this.upSign(val);
          return;
        },
        photo: function() {
          _this.upSign(val);
          return;
        },
        template: function() {
          _this.showTemplateModal = true;
          return;
        },
        text_and_sign: function() {
          _this.showTextTemplateModal = true;
          return;
        }
      };
      if (obj[key]) {
        this.signTypeChecked = _.cloneDeep(val);
        obj[key]();
      }
    },
    // 添加签名模板
    addTemplate() {
      this.upSign(this.signTypeChecked);
    },
    // 手写签名，拍照签名
    async upSign(signTypeChecked) {
      let _this = this;
      const { key, type, img, sign } = signTypeChecked;
      let signType = key || type;
      let signImg = img || sign;
      let para = {
        type: "HAND_SIGN_REQUEST",
        message: {
          connectionId: this.uuid,
          signType: signType,
          sign: this.isUpdata ? signImg : ""
        }
      };
      this.loading = this.$loading({
        lock: true,
        text: "调起签名客户端...",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)"
      });
      this.sendSocket({
        data: para,
        methods: {
          HAND_SIGN_RETURN: function(message) {
            callBack(message);
          },
          CAMERA_SIGN_RETURN: function(message) {
            callBack(message);
          },
          ONCLOSE: function() {
            _this.socketCallbackErr();
          },
          ONERROR: function() {
            _this.socketCallbackErr();
          }
        }
      });
      function callBack(message = {}) {
        const { code, message: backMessage } = message;
        if (code != "SUCCESS") {
          _this.$message.error(backMessage);
          _this.socketCallbackErr();
          return;
        }
        _this.socketCallback(message);
      }
    },
    // 多种签名类型弹框
    signClick() {
      // 只有一种签名方式时直接调起
      if (this.signType != "all_sign") {
        this.selectSign({ key: this.signType });
        return;
      }
      this.showSignModal = true;
    },
    // 判断是否需要追加签名
    autoSetDefault() {
      if (this.config.addSign) {
        this.setSignDefault();
      }
      if (this.config.addDate) {
        this.setSignTimeDefault();
      }
    },
    // 点击签名
    clickSign() {
      this.$set(this.textSign, "text", this.userInfo.name);
      this.autoSetDefault();
    },
    //设置签名默认值
    setSignDefault() {
      if (!this.textSign.sign) {
        this.$set(this.textSign, "sign", this.userInfo.name);
      }
    },
    // 设置签名默认时间
    setSignTimeDefault() {
      if (!this.textSign.date) {
        this.$set(this.textSign, "date", new Date().Format(this.config.format));
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.sz-tag-input {
  width: 100%;
  display: flex;
  flex-direction: column;
}
.signed-box {
  padding: 20px;
  &.text_and_sign.sign-inline {
    display: flex;
    align-items: flex-end;
    .edit-box {
      margin-top: 0;
      margin-left: 20px;
    }
    p {
      margin: 0;
    }
  }
  .sign-date {
    text-align: right;
  }
  .edit-box {
    margin-top: 20px;
    text-align: right;
  }
  .img-box {
    text-align: center;
    /deep/ .el-image {
      img {
      }
    }
  }
}
.sign-box {
  width: 100%;
  height: 100%;
  min-height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px dashed #26a57a;
  color: #26a57a;
  box-sizing: border-box;
}
.del {
  color: #f56c6c;
}
</style>
